
/*TinyFS demo file
 * Foaad Khosmood, Fall 2012
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "libTinyFS.h"


/* simple helper function to fill Buffer with as many inPhrase strings as possible before reaching size */
int fillBufferWithPhrase(char *inPhrase, char *Buffer, int size)
{
    int index = 0, i;
    if (!inPhrase || !Buffer || size <= 0 || size < strlen(inPhrase))
        return -1;

    while(index < size)
    {
        for(i = 0 ; inPhrase[i] != '\0' && (i+index < size); i++)
            Buffer[i+index] = inPhrase[i];
        index += i;
    }
    Buffer[size-1]='\0'; /* explicit null termination */
    return 0;
}

/* This program will create 2 files (of sizes 200 and 1000) to be read from or stored in the TinyFS file system. */
int main()
{
    char readBuffer;
    char *afileContent, *bfileContent, *cfileContent, *dfileContent, *efileContent, *writeFileBuffer; /* buffers to store file content */
    int afileSize = 200;  /* sizes in bytes */
    int bfileSize = 1000;
    int cfileSize = 110000;
    int dfileSize = 555;
    int efileSize = 876;
    int writeFileBufSize = 9999;
    int i, j;

    char phrase1[] = "hello world from (a) file ";
    char phrase2[] = "(b) file content ";
    char phrase3[] = "(c) what a great job we've done ";
    char phrase4[] = "thanks for (d) deadline extension. ";
    char phrase5[] = "(e) is for elephant... ";
    char phraseW[] = "(w)rite file buffer test phrase for RO mode ";
    char smiles[] = "(^_^)";

    fileDescriptor aFD,bFD,cFD,dFD,eFD;
    /* int i; */


    cfileContent = (char *)malloc(cfileSize * sizeof(char));
    if (fillBufferWithPhrase(phrase3,cfileContent,cfileSize) < 0)
    {
        perror("failed");
        return -1;
    }


    cFD = tfs_openFile("cfile");

    if (cFD < 0)
    {
        perror("tfs_openFile failed on cfile");
    }

    /* if readByte() fails, there was no afile1, so we write to it */
    if (tfs_writeFile(cFD,cfileContent) < 0)
    {
        perror("tfs_writeFile failed");
        printf("Failed to write cFile\n");
    }
    else
        printf("Successfully written to cfile\n");



    printf("THIS IS OUR FILE LIST AT THE START OF THE DEMO!\n");
    tfs_dir();

    afileContent = (char *)malloc(afileSize * sizeof(char));
    if (fillBufferWithPhrase(phrase1,afileContent,afileSize) < 0)
    {
        perror("failed");
        return -1;
    }

    bfileContent = (char *)malloc(bfileSize * sizeof(char));
    if (fillBufferWithPhrase(phrase2,bfileContent,bfileSize) < 0)
    {
        perror("failed");
        return -1;
    }

    dfileContent = (char *)malloc(dfileSize * sizeof(char));
    if (fillBufferWithPhrase(phrase4,dfileContent,dfileSize) < 0)
    {
        perror("failed");
        return -1;
    }

    efileContent = (char *)malloc(efileSize * sizeof(char));
    if (fillBufferWithPhrase(phrase5,efileContent,efileSize) < 0)
    {
        perror("failed");
        return -1;
    }

    writeFileBuffer = (char *)malloc(writeFileBufSize * sizeof(char));
    if (fillBufferWithPhrase(phraseW,writeFileBuffer,writeFileBufSize) < 0)
    {
        perror("failed");
        return -1;
    }

    /* print content of files for debugging */
    printf("(a) File content: %s\n(b) File content: %s\nReady to store in TinyFS\n", afileContent, bfileContent);
    printf("(d) File content: %s\n(e) File content: %s\nReady to store in TinyFS\n", dfileContent, efileContent);

    /* read or write files to TinyFS */




    aFD = tfs_openFile("afile");

    if (aFD < 0)
    {
        perror("tfs_openFile failed on afile");
    }

    /* now, was there already a file named "afile" that had some content? If we can read from it, yes!
     *  * If we can't read from it, it means the very beginning of the file is the null character so therefore,
     *   * it's a new file and empty */
    if (tfs_readByte(aFD,&readBuffer) < 0)
    {
        /* if readByte() fails, there was no afile1, so we write to it */
        if (tfs_writeFile(aFD,afileContent) < 0)
        {
            perror("tfs_writeFile failed");
        }
        else
            printf("Successfully written to afile\n");
    }
    else
    {
        /* if yes, then just read and print the rest of afile that was already there */
        printf("\n*** reading afile from TinyFS: \n%c",readBuffer); /* print the first byte already read */
        /* now print the rest of it, byte by byte */

        while((tfs_readByte(aFD,&readBuffer) >= 0) && (readBuffer != '\0'))
            printf("%c",readBuffer);


        /* now delete afile so next time the demo is run, a new one is created */
        tfs_deleteFile(aFD);
    }

    /* now bfile tests */
    bFD = tfs_openFile("bfile");

    if (bFD < 0)
    {
        perror("tfs_openFile failed on bfile");
    }

    if (tfs_readByte(bFD,&readBuffer) < 0)
    {
        if (tfs_writeFile(bFD,bfileContent) < 0)
        {
            perror("tfs_writeFile failed");
        }
        else
        {
            printf("Successfully written to bfile\n");
            printf("\nSeeking to block-straddling point for writeByte test\n");
            tfs_seek(bFD, 230);
            for( i = 0; i < 20; i++)
            {
                for(j = 0; j < 5; j++)
                {
                    if(tfs_writeByte(bFD, smiles[j]) == -1)
                    {
                        i = 20;
                        break;
                    }
                }
            }
            printf("\nSeeking to near-end of file for writeByte test\n");
            tfs_seek(bFD, 980);
            for( i = 0; i < 20; i++)
            {
                for(j = 0; j < 5; j++)
                {
                    if(tfs_writeByte(bFD, smiles[j]) == -1)
                    {
                        i = 20;
                        break;
                    }
                }

            }
        }
    }
    else
    {
        printf("\n*** reading bfile from TinyFS: \n%c",readBuffer);
        while((tfs_readByte(bFD,&readBuffer) >= 0) && (readBuffer != '\0'))
            printf("%c",readBuffer);

        tfs_deleteFile(bFD);
    }


    dFD = tfs_openFile("dfile");

    if (dFD < 0)
    {
        perror("tfs_openFile failed on dfile");
    }

    /* if readByte() fails, there was no afile1, so we write to it */
    if (tfs_writeFile(dFD,dfileContent) < 0)
    {
        perror("tfs_writeFile failed");
    }
    else
        printf("Successfully written to dfile\n");



    eFD = tfs_openFile("efile");

    if (eFD < 0)
    {
        perror("tfs_openFile failed on efile");
    }

    if (tfs_readByte(eFD,&readBuffer) < 0)
    {
        /* if readByte() fails, there was no afile1, so we write to it */
        if (tfs_writeFile(eFD,efileContent) < 0)
        {
            perror("tfs_writeFile failed");
        }
        else
            printf("Successfully written to efile\n");
    }
    else
    {
        printf("\n*****<<<<<Seeking to the 'middle' of efile before reading.>>>>>*****\n");
        tfs_seek(eFD,550);
        /* if yes, then just read and print the rest of afile that was already there */
        printf("\n*** reading efile from TinyFS: \n%c",readBuffer); /* print the first byte already read */
        /* now print the rest of it, byte by byte */

        while((tfs_readByte(eFD,&readBuffer) >= 0) && (readBuffer != '\0'))
            printf("%c",readBuffer);


        /* now delete afile so next time the demo is run, a new one is created */
    }

    printf("\n\n*****<<<<< TESTING DIRECTORY FUNCTIONS >>>>>*****\n");
    tfs_dir();

    if(tfs_rename("efile", "ffile") == -1)
    {
        printf("rename failed\n");
    }

    tfs_dir();

    printf("*****<<<<< DONE TESTING DIRECTORY FUNCTIONS >>>>>*****\n");
    /*** Testing Read Only functionality ****/
    printf("\n*****<<<<< TESTING READ ONLY MODE >>>>>*****\n");
    tfs_makeRO("dfile"); /* make dfile read only */

    tfs_deleteFile(dFD); /* try to delete dFile */
    tfs_rename("dfile", "tfile"); /* try to rename dfile */
    tfs_writeFile(dFD, writeFileBuffer); /* try to write file to dFD */
    tfs_writeByte(dFD, 'c');   /* try to write byte to dFD */

    printf("*****<<<<< BACK TO READ WRITE MODE >>>>>*****\n");
    tfs_makeRW("dfile"); /* make dfile read write again */

    /*  tfs_deleteFile(dFD); */

    tfs_dir();

    free(efileContent);
    free(dfileContent);
    free(cfileContent);
    free(bfileContent);
    free(afileContent);

    return 0;
}
